/*
 * @Author       : Bing Chen chenbing@iocharger.com
 * @Date         : 2024-05-20 17:16:48
 * @LastEditors  : Bing Chen chenbing@iocharger.com
 * @LastEditTime : 2025-03-15 12:50:23
 * @FilePath     : \openchaoji-corelib\secc\utility\OpenChaoJi_secc_utility_session.h
 * @Description  : 本文件定义SECC Utility层 Session 会话层 模块
 * 				   本模块管理传输层, 数据队列和链路层三个模块, 实现对system的的数据封装收发
 *
 * Copyright (c) 2025 OpenChaoJi
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the icense for the specific language governing permissions and
 * limitations under the License.
 *
 */


#ifndef __OPEN_CHAOJI_SECC_UTILITY_SESSION_H__
#define __OPEN_CHAOJI_SECC_UTILITY_SESSION_H__

#include "../../shared/include/OpenChaoJi_shared.h"
#include "OpenChaoJi_secc_utility_linkage.h"

/**
 * @brief 本模块的上下文数据结构, 内部包含传输层, 数据队列, 链路层三个模块的句柄
 */
struct OpenChaoJi_secc_context_utility_session;

/**
 * @brief 创建本模块的上下文时需要传入的参数
 */
struct OpenChaoJi_secc_create_info_utility_session {
	int tag;

    /**
     * 应用启动创建上下文时, 各集成厂家可以传一个与本库无关的静态数据指针, 本库将保存该指针
     * 当app/hal层使用上下文时, 各集成厂家可以自行读取该数据
     * 一般最佳实践是传递本secc对应的索引序号, IO-MAP等
    */
    OpenChaoJi_hal_handle hal_handle;

	/**
     * 本SECC使用的系统类型, 目前仅支持A/B两类, CHAdeMO/CCS1/CCS2暂不支持
    */
    enum OpenChaoJi_secc_gbt27930_type secc_gbt27930_type;

	union
	{
		struct {
			int dummy;
		} gbt27930_a;

		struct {
			int dummy;
		} gbt27930_b;
	} gbt27930_info;

    /**
     * session模块管理了三个子模块
     */
    struct OpenChaoJi_create_info_utility_data_buff       data_buff;

    struct OpenChaoJi_secc_create_info_utility_linkage    linkage;

};


/**
 * @brief 初始化
 *	      1. 创建数据队列句柄, 用于准备收发数据
 *        2. 创建传输层句柄, 用于进行底层数据通信
 *        3. 创建链路层句柄, 用于进行链路协商和链路监测(A类系统不需要)
 *
 * @param info 初始化信息
 * @return 成功返回创建的上下文指针，失败返回NULL。
 */
struct OpenChaoJi_secc_context_utility_session * OpenChaoJi_secc_utility_session_init(const struct OpenChaoJi_secc_create_info_utility_session * info);

/**
 * @brief 销毁, 销毁链路层/传输层/数据队列句柄
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @return 成功返回0，失败返回-1。
 */
int OpenChaoJi_secc_utility_session_term(struct OpenChaoJi_secc_context_utility_session * context);

/**
 * @brief 复位, 复位链路层/传输层/数据队列句柄
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @return 成功返回0，失败返回-1。
 */
int OpenChaoJi_secc_utility_session_reset(struct OpenChaoJi_secc_context_utility_session * context);

/**
 * @brief 启动数据通信, system在pilot导引确认后开始启动数据通信
 *        1. 传输层启动连接(connect或者listen/accept), 非阻塞
 *        2. 传输层连接成功后, 链路层依赖传输层进行链路协商(A类系统不需要)
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @return 成功返回0，失败返回-1。
 */
int OpenChaoJi_secc_utility_session_start(struct OpenChaoJi_secc_context_utility_session* context);

/**
 * @brief 停止数据通信, system停止流程或者进入故障时需要断开连接
 *        1.
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @return 成功返回0，失败返回-1。
 */
int OpenChaoJi_secc_utility_session_stop(struct OpenChaoJi_secc_context_utility_session* context);

/**
 * @brief 写入数据, system运行时, 如果需要发送数据给evcc, 则通过本方法写入, 实际是传递给数据队列句柄
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @param send_data 待发送的数据结构
 * @return 读到数据返回0，读不到数据返回-1。
 */
int OpenChaoJi_secc_utility_session_data_write(struct OpenChaoJi_secc_context_utility_session *context, struct OpenChaoJi_utility_data_buff_send_data * send_data);

/**
 * @brief 读取数据, system运行时, 需要从本模块的读取有效数据, 一次读取一个包. 每次service运行会循环调用本函数读取, 直到读光. 实际是传递给数据队列句柄
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @param recv_data 待读取数据结构, 注意读取方需要自行free接收的数据区
 * @return 读到数据返回0，读不到数据返回-1。
 */
int OpenChaoJi_secc_utility_session_data_read(struct OpenChaoJi_secc_context_utility_session *context, struct OpenChaoJi_utility_data_buff_recv_data * recv_data);

/**
 * @brief 接收数据服务, session存在异步处理, 也包含内部的链路处理, 所以每次service触发内部处理
 *        1. 调用传输层service, 使得传输层可以处理当前交互数据(例如消息应答等)
 *        2. 从传输层读取完整数据包
 *           1) 如果能读取到, 则跳转步骤3
 *           2) 如果不能读取到, 则进入步骤4
 *        3. 处理完整数据包
 *           1) 如果是链路层相关数据包, 则交给链路模块处理(OpenChaoJi_secc_utility_linkage_got_data)
 *           2) 其他数据包交给数据队列模块暂存(OpenChaoJi_utility_data_buff_queue_write), 同时需要告知链路检测模块有数据到达(OpenChaoJi_secc_utility_linkage_got_data)
 *           3) 然后跳转到步骤1, 继续调用传输层service, 尝试读取下一个完整数据包
 *        4. 调用链路层serivce处理, 保证链路层能进行状态切换
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @return 无
 */
void OpenChaoJi_secc_utility_session_service_try_recv(struct OpenChaoJi_secc_context_utility_session * context);

/**
 * @brief 发送数据服务, serivce每次运行system后会再调用本方法触发数据区确认到期数据自动发送(OpenChaoJi_utility_data_buff_service_try_send)
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @return 无
 */
void OpenChaoJi_secc_utility_session_service_try_send(struct OpenChaoJi_secc_context_utility_session* context);

/**
 * @brief 会话层连接是否已经建立, 如连接未建立, 或已断开, 则system需要根据超时情况决定状态跳转
 * 		  1. 传输层已经建立连接, 或连接未断开
 *        2. 数据链路层已经完成版本协商 或链路检测未进入故障状态
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @return 连接失败或者未连续技返回0, 连接成功返回1，连接中返回2
 */
enum OpenChaoJi_secc_utility_session_connect_status {
    OPENCHAOJI_SECC_UTILITY_SESSION_CONNECT_STATUS_DISCONNECTED = 0,
    OPENCHAOJI_SECC_UTILITY_SESSION_CONNECT_STATUS_CONNECTED    = 1,
    OPENCHAOJI_SECC_UTILITY_SESSION_CONNECT_STATUS_CONNECTING   = 2,
};
enum OpenChaoJi_secc_utility_session_connect_status OpenChaoJi_secc_utility_session_is_connected(struct OpenChaoJi_secc_context_utility_session* context);

/**
 * @brief: 会话层服务的状态机处理方法, 需要由系统定时触发, 也可立即触发，一般建议不超过20ms调用一次
 *         注意, 由于兼容非系统方式实现, 所以本项目所有方法默认处于同一线程, 如厂家通过操作系统实现, 厂家需要保证线程安全
 * @param {OpenChaoJi_secc_context_utility_session *} context
 * @return {*}
 */
void OpenChaoJi_secc_utility_session_service(struct OpenChaoJi_secc_context_utility_session* context);

#endif
